package com.xc.utils.redis;

import com.xc.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;

import java.text.SimpleDateFormat;

/**
 * Created by xiongcan on 2018/1/21.
 *
 *      <dependency>
         <groupId>org.codehaus.jackson</groupId>
         <artifactId>jackson-mapper-asl</artifactId>
         <version>1.9.12</version>
        </dependency>
 */
@Slf4j
public class JsonUtil {

    // 用户在登陆时候 保存到redis服务器的是一个String，需要把user 序列化json
    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        //  SerializationConfig 序列化配置
        //  将对象的所有的字段全部列入
        objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
        //  取消默认的timestamp的形式
        objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS,false);
        //  忽略空bean转json的错误
        objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS,false);
        //  所有的日期格式统一成如下的 yyyy-MM-dd HH:mm:ss 格式
        objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtil.STANDARD_FORMAT));

        //  DeserializationConfig 反序列化配置
        //  忽略 在反序列化时，json字符串中存在，但是java对象中不存在的情况
        objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES,false);
    }

    //  obj to json string -- > writeValueAsString
    public static <T> String obj2String(T obj){
        if(obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : objectMapper.writeValueAsString(obj);
        }catch (Exception e){
            log.warn("XC JsonUtil Parse obj to string error " , e);
            return null;
        }
    }

    //  obj to json string 返回格式化好的json字符串
    public static <T> String obj2StringPretty(T obj){
        if(obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : objectMapper
                    .writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        }catch (Exception e){
            log.warn("XC JsonUtil Parse obj to string error " , e);
            return null;
        }
    }

    //  json string to obj -- > readValue
    //  ps : 这个只适用于单对象的反序列化
    public static <T> T string2Obj(String str , Class<T> clazz){
        if(StringUtils.isEmpty(str) || clazz == null){
            //  如果str是空的，或者没指定类型
            return null;
        }
        try {
            return clazz.equals(String.class) ? (T)str : objectMapper.readValue(str,clazz);
        }catch (Exception e){
            log.warn("XC 1 JsonUtil Parse string to obj error" , e);
            return null;
        }
    }

    //  范型反序列化1。  json string to obj
    //  ps : 这个适用于List，Map的反序列化
    //  JsonUtil.string2Obj(str, new TypeReference<List<User>>() {});
    public static <T> T string2Obj(String str , TypeReference<T> typeReference){
        if(StringUtils.isEmpty(str) || typeReference == null){
            return null;
        }
        try {
            return (T)(typeReference.getType().equals(String.class) ? str :
                        objectMapper.readValue(str , typeReference));
        }catch (Exception e){
            log.warn("XC 2 JsonUtil Parse string to obj error" , e);
            return null;
        }
    }
    //  范型反序列化2.    Class<?>...表示可变长参数，当为多个传数组
    //  JsonUtil.string2Obj(str , List.class , User.class);
    public static <T> T string2Obj(String str , Class<?> collectionClass
            , Class<?>... elementClasses){

        JavaType javaType = objectMapper.getTypeFactory()
                .constructParametricType(collectionClass,elementClasses);

        try {
            return objectMapper.readValue(str , javaType);
        }catch (Exception e){
            log.warn("XC 3 JsonUtil Parse string to obj error" , e);
            return null;
        }
    }







    public static void main(String[] args) {
//        User user = new User();
//        user.setId(1);
//        user.setEmail("xiongcan@163.com");
//
//        String userjson = JsonUtil.obj2String(user);
//        String userjsonpretty = JsonUtil.obj2StringPretty(user);
//
//        log.info("userjson:{}" , userjson);
//        //userjson:{"id":1,"username":null,"password":null,"email":"xiongcan@163.com","phone":null,"question":null,"answer":null,"role":null,"createTime":null,"updateTime":null}
//        log.info("userjsonpretty:{}" , userjsonpretty);
        //userjsonpretty:{
//                "id" : 1,
//                "username" : null,
//                "password" : null,
//                "email" : "xiongcan@163.com",
//                "phone" : null,
//                "question" : null,
//                "answer" : null,
//                "role" : null,
//                "createTime" : null,
//                "updateTime" : null


//        JsonUtil.string2Obj(str, new TypeReference<List<User>>() {});
//        JsonUtil.string2Obj(str , List.class , User.class);

    }



}




